package dse.modules;

import java.util.Map;

import dse.*;
import dse.messages.MessageType;

public class GeneralMessageSizeCalculator implements MessageSizeCalculator {
	private int baseSize;
	private int idSize;
	private static int macSize = 16;
	
	public void initalize (
			ExperimentConfiguration systemSettings,
			Map<String, String> moduleSettings
			) 
	throws DseException
	{
		ModuleUtil.SettingsReader sr = ModuleUtil.getSettingsReader(
				this.getClass(), moduleSettings
				);
		baseSize = sr.getInteger("base-message-size");
		idSize  = sr.getInteger("id-size");
	}
	
	public long calculateSize (MessageType messageType) {
		assert messageType != MessageType.ClustersThatMightHaveDataObject;
		assert messageType != MessageType.ShareDataTransfer;
		
		if (//messageType == MessageType.RequestShareLocal || 
			messageType == MessageType.RequestShareForeign || 
			messageType == MessageType.HasShare  || 
			messageType == MessageType.LocateClustersWithDataObject ||
			messageType == MessageType.ActivateCachedShare ||
			messageType == MessageType.RequestShare ||
			messageType == MessageType.VersionResponseV3 ||
			messageType == MessageType.ShareUpdateV5Response ||
			messageType == MessageType.RequestDesignatedShareRep
			)
			return baseSize + idSize*2;
		else if (messageType == MessageType.Redirect ||
				//messageType == MessageType.GetDataObjectInfo ||
				messageType == MessageType.CanAddDataShare ||
				messageType == MessageType.RequestDataObject ||
				messageType == MessageType.RequestDataObjectLocal ||
				messageType == MessageType.HasDataObject || 
				messageType == MessageType.DownloadAndCacheDataObject ||
				messageType == MessageType.RequestVersion ||
				messageType == MessageType.RequestLatestShare ||
				messageType == MessageType.RequestLatestShareV2 ||
				messageType == MessageType.RequestVersionV3 ||
				messageType == MessageType.ShareUpdateV4Response ||
				messageType == MessageType.RequestVersionQuorum ||
				messageType == MessageType.RequestShareV2 ||
				messageType == MessageType.ActivateUpdateShare ||
				messageType == MessageType.UpdateConfirm ||
				messageType == MessageType.RequestMaxTS ||
				messageType == MessageType.RequestLatestAndVersion ||
				messageType == MessageType.RequestLatestAndVersionV2 ||
				messageType == MessageType.ReleaseUpdateLock ||
				messageType == MessageType.UpdateLockResponse ||
				messageType == MessageType.RequestVersionRep ||
				messageType == MessageType.TurnVersionRepOn ||
				messageType == MessageType.RequestVersionTLO ||
				messageType == MessageType.RequestLCShare ||
				messageType == MessageType.RequestLCVersion
				)
			return baseSize + idSize;
		else if (messageType == MessageType.DownloadAndCacheShare || 
				messageType == MessageType.UpdateSuccessV3 ||
				messageType == MessageType.RemoveOldVersionV3 ||
				messageType == MessageType.VersionResponseQuorum ||
				messageType == MessageType.ReadRequest ||
				messageType == MessageType.RequestLock ||
				messageType == MessageType.ReleaseLock ||
				messageType == MessageType.RequestUpdateLock ||
				messageType == MessageType.RequestDesignatedShare ||
				messageType == MessageType.RequestPreviousShareV2 ||
				messageType == MessageType.RequestPreviousShare ||
				messageType == MessageType.UpdateSuccessTLO ||
				messageType == MessageType.SVR ||
				messageType == MessageType.RequestShareWithVersion ||
				messageType == MessageType.LCVersionResponse ||
				messageType == MessageType.VersionNumberResponse
				)
			return baseSize + Version.getSize(); // dobj + share + cluster
		else if(messageType == MessageType.RequestDesignatedShareTLO ||
				messageType == MessageType.ReadComplete ||
				messageType == MessageType.ReadCompleteTLO
				)
			return baseSize + idSize*4;
		else if (messageType == MessageType.DataObjectInfoResponse)
			return baseSize + idSize*8; // For extra info!
		else if (messageType == MessageType.SendVersion)
			return baseSize + Version.getSize();
		else if(messageType == MessageType.RequestVersionNumber ||
				messageType == MessageType.BoundaryVersion ||
				messageType == MessageType.RequestVersionShare)
			return baseSize + idSize + Version.getSize();
		else if (messageType == MessageType.SendMAC)
			return baseSize + Version.getSize();
		return baseSize;
	}

	public long calculateSize (
			MessageType messageType, int elements, int elementSizeModifier
			)
	{
		// The extra idSize is to include the number of ids...
		return baseSize + idSize + elements*idSize*elementSizeModifier;
	}

	public long calculateSize (MessageType messageType, DataObject dataObject) {
		if(messageType == MessageType.ShareUpdate ||
			messageType == MessageType.ShareDownload ||
			messageType == MessageType.ShareUpdateV2 ||
			messageType == MessageType.ShareUpdateV3 ||
			messageType == MessageType.ShareUpdateV4 ||
			messageType == MessageType.ShareUpdateV5 ||
			messageType == MessageType.ShareUpdateV6 ||
			messageType == MessageType.ShareDataTransfer ||
			messageType == MessageType.ShareUpdateCVS ||
			messageType == MessageType.ShareUpdateAVID ||
			messageType == MessageType.ShareUpdateOSV ||
			messageType == MessageType.VersionShareResponse ||
			messageType == MessageType.SendMACAVID
			)
			return baseSize + dataObject.shareSize()+Version.getSize();
		else if(messageType == MessageType.ShareUpdateHen)
			return baseSize + dataObject.shareSize() + Version.getSize() - idSize;
		else if(messageType == MessageType.MACResponse)
			return baseSize + this.idSize + dataObject.shareCount()*macSize;
		else if(messageType == MessageType.SendMACHen)
			return baseSize + Version.getSize() + dataObject.shareCount()*macSize;
		else if(messageType == MessageType.ShareUpdateTLO)
			return baseSize + dataObject.shareSize()+Version.getSize()+idSize;
		return baseSize + dataObject.size();
	}

	public long calculateSize (
			MessageType messageType, 
			BloomFilter<DataObject> bloomFilter
			)
	{
		return baseSize + bloomFilter.getM();
	}
	/*public long calculateSize (MessageType messageType, DataShare dataShare) {
		return baseSize + dataShare.getSize() + Version.getSize();
	}*/
	
	public long calculateSize (
			MessageType messageType, DataObject dobj, int elements, int elementSizeModifier
			)
	{
		// The extra idSize is to include the number of ids...
		return baseSize + idSize + elements*idSize*elementSizeModifier + dobj.shareSize() + Version.getSize();
	}
}
